home *** CD-ROM | disk | FTP | other *** search
/ Beginning Mac Programming / Beginning Mac Programming.bin / pc / Open Me for REALbasic 3 / REALbasic 3.2 / Goodies / 3rd Party Demos / 3rd Party Plugins / Misc / PEVocoder 1.0 (PPC) / PEVocodePlugin Source Code / Plugin Source.cpp < prev    next >
Encoding:
Text File  |  2000-05-09  |  11.6 KB  |  375 lines

  1. /*
  2.  * Starter for REALbasic 2.0 plugins
  3.  *
  4.  * Currently, this code shows how to add new global methods and how
  5.  * to create or extend classes to RB.
  6.  * Creating Controls is not shown in here - see the sample projects
  7.  * in RB's plugin SDK for that.
  8.  *
  9.  * The accompanying project file was created using CodeWarrior Pro 4
  10.  * with the latest updates from Metrowerks' FTP Site (including IDE 3.3).
  11.  *
  12.  * This code is freeware, you may use and extend it as you like.
  13.  * It was written on Nov 21, 99 by Thomas Tempelmann.
  14.  * Updated Jan 18, 2000 by TT: Verified with RB 2.1a25 that classes work
  15.  *   now in x86 plugins, too.
  16.  * Updated Jan 28, 2000 by TT: ("Ruslan special") Now also initializes
  17.  *   static C++ constructors.
  18.  * Updated Feb 1, 2000 by TT: Now also shows how to pass Boolean and
  19.  *   Double arguments. Also added "#pragma mpwc on" to this and to the
  20.  *   "PluginMain.cpp" for 68K compiles, and disabled the global MPW C
  21.  *   calling option in the project settings for "68K Processor".
  22.  *   Removed the "far" modifier from a function prototype to avoid an
  23.  *   error msg from the Pro 5's compiler.
  24.  *
  25.  * More RB-related stuff can be found here: <http://www.tempel.org/rb/>
  26.  *
  27.  * Enjoy and contribute!
  28.  */
  29.  
  30.  
  31. /*
  32.  * -----------
  33.  *  Attention
  34.  * -----------
  35.  *
  36.  * In case you want to create plugins that can be used under Windows, too:
  37.  *
  38.  * Versions of RB before 2.1a24 (that is, RB versions before January 2000)
  39.  * did not handle Windows plugins correctly: It was impossible to use x86
  40.  * (Windows) plugins that added a new class. If you tried to call any method
  41.  * or property of a new class from a plugin, you'll get a crash in your
  42.  * Windows app. RB 2.1a25 has this problem fixed.
  43.  *
  44.  * That means: If you re-distribute plugins for Windows, you have to let
  45.  * your users know that they cannot use them with RB versions before 2.1a24.
  46.  */
  47.  
  48. //--------------------
  49. // Your includes here
  50. //--------------------
  51.  
  52. #include <string.h>    // this and any other includes must come _before_ the "pragma mpwc on"!
  53. #ifndef WIN32
  54.     #include <MacMemory.h>
  55. #else
  56.     //static void DebugStr(unsigned char* p) {}
  57.     //static void Debugger() {}
  58. #endif
  59.  
  60. //-------------------------
  61. // RB header includes here
  62. //-------------------------
  63.  
  64. // Attention - if you include any other headers, like those from the C stdlib,
  65. // or PowerPlant, you must place those includes _before_ the following
  66. // pragma that turns on mpwc calling conventions, or you might get crashes in
  67. // 68K plugins!
  68. #if TARGET_CPU_68K
  69.     //#pragma mpwc on
  70. #endif
  71.  
  72. #include "rb_plugin.h"    // this include must come _after_ the "pragma mpwc on"!
  73.  
  74.  
  75. //-----------------------
  76. // Some type definitions
  77. //-----------------------
  78.  
  79.     // "RBinteger" represents a RB "Integer" type:
  80.  
  81. typedef long RBinteger;
  82.  
  83.     // "RBboolean" represents a RB "Boolean" type (when passed as a parameter or returned from a function):
  84.  
  85. //typedef Boolean RBboolean;
  86.  
  87.     // "RBdouble" represents a RB "Double" type:
  88.  
  89. #if TARGET_CPU_68K
  90.     typedef Float80 RBdouble;    // Attention: for this to work, "Floating Point" in the "68K Processor" options must be set to "SANE".
  91. #else
  92.     typedef double RBdouble;
  93. #endif
  94.  
  95.     /*
  96.      * Note: Passing Singles to plugin functions is currently (RB 2.1a26) not correctly supported
  97.      * in RB for 68K code, so I suggest to always only use Doubles as parameters!
  98.      */
  99.  
  100.  
  101.  
  102. //-----------------------
  103. // Add global RB methods
  104. //-----------------------
  105.  
  106. static RBinteger sampleIntFunc (RBinteger a, RBinteger b)
  107. // Adds the two passed values and returns the result
  108. {
  109.     return a + b;
  110. }
  111.  
  112. static RBdouble sampleDblFunc (RBdouble a, RBdouble b)
  113.     {
  114.         return a + b;
  115.     }
  116.  
  117.  
  118. static void copyBytes (char const* from, char* to, long amount)
  119. // This is just a little helper function to copy some bytes
  120. // (Attention: this may not work when the memory of "to" and "from"
  121. // is overlapping!)
  122. {
  123.     while (amount-- > 0) {
  124.         *to++ = *from++;
  125.     }
  126. }
  127.  
  128. // For examples on handling other RB data types, such as Double and Boolean,
  129. // see the code for handling class properties further below.
  130.  
  131. static REALstring sampleStrFunc (REALstring a, REALstring b)
  132. // Concatenates the two strings and returns the result
  133. {
  134.     // get the length of the two strings
  135.     long la, lb;
  136.     la = a->Length();
  137.     lb = b->Length();
  138.     
  139.     // create a new string object that is large enough to hold the sum of the two strings
  140.     REALstring str = REALBuildString (nil, la + lb);
  141.     
  142.     // now copy the two strings' contents into the new string buffer
  143.     copyBytes (a->CString(), (char*)str->CString(), la);
  144.     copyBytes (b->CString(), (char*)str->CString() + la, lb);
  145.     
  146.     return str;
  147. }
  148.  
  149. static REALmethodDefinition pluginMethodArray[] = {
  150.     { (REALproc) sampleIntFunc, REALnoImplementation, "SampleIntFunc(A as Integer, B as Integer) as Integer" },
  151.     { (REALproc) sampleDblFunc, REALnoImplementation, "SampleDoubleFunc(A as Double, B as Double) as Double" },
  152.     { (REALproc) sampleStrFunc, REALnoImplementation, "SampleStrFunc(A as String, B as String) as String" },
  153. };
  154.  
  155.  
  156. //------------------------------------------------------
  157. // Create a new RB class or extend an existing RB class
  158. //------------------------------------------------------
  159.  
  160.  
  161.     // If you want to create a new class, set the following macro
  162.     // to 0;
  163.     // If you want to extend an existing RB class, such as FolderItem,
  164.     // Date or Application, set the value to 1:
  165.  
  166. #define doExtentTheClass 0 // if 0, then it'll create a new class instead
  167.  
  168.  
  169. extern REALclassDefinition sampleClass;    // forward declaration
  170.  
  171.  
  172.     /*
  173.      * The following structure defines internal storage space for your
  174.      * class. This space is not automatically visible to the user, but
  175.      * only if you add property accessor routines like the ones below
  176.      * (see sampleIntGetter and following).
  177.      */
  178.  
  179. struct sampleClassData
  180. {
  181.     // Note: If you _extend_ a class, the properties here will not be zeroed,
  182.     //       nor will the constructor be called. That means that these properties
  183.     //       will not get any defined values - they may contain random data if
  184.     //       the class is instantiated! I consider this a bug in RB.
  185.     
  186.     long    aInteger;
  187.     Boolean    aBoolean;
  188.     double    aDouble;
  189. };
  190.  
  191.  
  192.     /*
  193.      * The following code implements the constructor and destructor of the class.
  194.      *
  195.      * Note that those will only be called when you define a _new_ class, but not
  196.      * if you extends a class (this is a bug in RB 2.1a25 and might perhaps get
  197.      * fixed later).
  198.      */
  199.  
  200. static void sampleClassConstructor (REALobject instance)
  201. {
  202.     ClassData (sampleClass, instance, sampleClassData, me);
  203.  
  204.     // you can initialize objects of "me" here ...
  205.     
  206.     me->aInteger = 1234;
  207. }
  208.  
  209. static void sampleClassDestructor (REALobject instance)
  210. {
  211.     ClassData (sampleClass, instance, sampleClassData, me);
  212.  
  213.     // close & dispose objects of "me" here
  214.     //
  215.     // (e.g., if you opened a file or allocated memory, you need to release it here again!)
  216. }
  217.  
  218.  
  219.     /*
  220.      * The following code shows how to deal with RB's Integer values (which is quite simple)
  221.      */
  222.  
  223. static RBinteger sampleIntGetter (REALobject instance, long param)
  224. // This is called when RB reads a property of your class
  225. {
  226.     ClassData (sampleClass, instance, sampleClassData, me);
  227.     return me->aInteger;
  228. }
  229.  
  230. static void sampleIntSetter (REALobject instance, long param, RBinteger value)
  231. // This is called when RB assigns a value to a property of your class
  232. {
  233.     ClassData (sampleClass, instance, sampleClassData, me);
  234.     me->aInteger = value;
  235. }
  236.  
  237.  
  238.     /*
  239.      * The following code shows how to deal with RB's Boolean values. Note that RB
  240.      * passes its Boolean arguments as 32 bit (long) values. Also note that beta versions
  241.      * of RB 2.1 have a bug in their 68K code that will instead pass them as 8 bit values.
  242.      * RB 2.0.2 and before did not have this bug.
  243.      * This bug should be fixed before the final 2.1 comes out, hopefully.
  244.      */
  245.  
  246. static Boolean sampleBoolGetter (REALobject instance, long param)
  247. {
  248.     ClassData (sampleClass, instance, sampleClassData, me);
  249.     return me->aBoolean;    // 1 is "true", 0 is "false"
  250. }
  251.  
  252. static void sampleBoolSetter (REALobject instance, long param, Boolean value)
  253. {
  254.     ClassData (sampleClass, instance, sampleClassData, me);
  255.     me->aBoolean = value;
  256. }
  257.  
  258.  
  259.     /*
  260.      * The following code shows how to deal with RB's Double values - note that 68K code
  261.      * needs a special handling, because in 68K a RB double is a 80 bit value, while in
  262.      * PPC and x86 it is a 64 bit value:
  263.      */
  264.  
  265. static double sampleDoubleGetter (REALobject instance, long param)
  266.     {
  267.         ClassData (sampleClass, instance, sampleClassData, me);
  268.         return me->aDouble;
  269.     }
  270.  
  271. static void sampleDoubleSetter (REALobject instance, long param, double value)
  272. {
  273.     ClassData (sampleClass, instance, sampleClassData, me);
  274.     me->aDouble = value;
  275.     // note for 68K: the 64 bit "double" value is converted into RB's 80 bit "extended" value here
  276. }
  277.  
  278.  
  279.     /*
  280.      * The following code shows how to implement methods of a class
  281.      */
  282.  
  283. static void sampleClassMethod (REALobject instance, RBinteger factor)
  284. // This is called when RB calls a method of your class
  285. {
  286.     ClassData (sampleClass, instance, sampleClassData, me);
  287.     me->aInteger *= factor;
  288. }
  289.  
  290.     /*
  291.      * The following structures declare the class and its members
  292.      */
  293.  
  294. static REALproperty sampleClassProperties[] = {
  295.     { nil, "SampleInt", "Integer",   0, (REALproc) sampleIntGetter,    (REALproc) sampleIntSetter,    0 },
  296.     { nil, "SampleBool", "Boolean",  0, (REALproc) sampleBoolGetter,   (REALproc) sampleBoolSetter,   0 },
  297.     { nil, "SampleDouble", "Double", 0, (REALproc) sampleDoubleGetter, (REALproc) sampleDoubleSetter, 0 },
  298. };
  299.  
  300. static REALmethodDefinition sampleClassMethods[] = {
  301.     // defines a method:
  302.     { (REALproc) sampleClassMethod, REALnoImplementation, "SampleMethod(factor as Integer)"},
  303. };
  304.  
  305. static REALclassDefinition sampleClass = {
  306.     kCurrentREALControlVersion,
  307.     #if doExtentTheClass
  308.         "aRBClassName",    // <- put the name of the to be extended class here, like "FolderItem"
  309.     #else
  310.         "SampleClass",    // <- this is the name of the class you're adding with this plugin
  311.     #endif
  312.     nil,
  313.     sizeof(sampleClassData),
  314.     0,
  315.     #if doExtentTheClass
  316.         // Unfortunately, for extended classes, we don't get called when an obj is con-/destructed.
  317.         // (this is a current RB restriction and might be changed in a later version, hopefully)
  318.         nil, nil,
  319.     #else
  320.         (REALproc) sampleClassConstructor, (REALproc) sampleClassDestructor,
  321.     #endif
  322.     sampleClassProperties,
  323.     sizeof(sampleClassProperties) / sizeof(REALproperty),
  324.     sampleClassMethods,
  325.     sizeof(sampleClassMethods) / sizeof(REALmethodDefinition),
  326.     nil,
  327.     0
  328. };
  329.  
  330.  
  331. // To initialize the static C++ objects, we must call a special routine
  332. // that the linker will generate. Here's the preperation for this:
  333. #ifdef WIN32
  334.     extern "C" far void _RunInit(void);
  335.     #define __InitCode__ _RunInit
  336. #elif defined(powerc)
  337.     extern "C" void __sinit(void);
  338.     #define __InitCode__ __sinit
  339. #else // it's 68K
  340.     extern "C" far void __InitCode__ (void);
  341. #endif
  342. extern "C" void __destroy_global_chain (void);    // This one should be called when
  343.                                                 // the plugin is unloaded - but how?
  344.  
  345. void PluginEntry (void)
  346. {
  347.     /*
  348.      * This is the main entry that is called when your plugin is loaded by REALbasic
  349.      * or when a built application that uses your plugin is launched.
  350.      *
  351.      * Here you tell RB about what your plugin provides. Call:
  352.      *  • REALRegisterMethod() to add gobal methods
  353.      *  • REALRegisterClass() to add new classes
  354.      *  • REALRegisterClassExtension() to extent existing classes
  355.      *  • REALRegisterControl() to add new controls
  356.      */
  357.  
  358.     __InitCode__ ();    // calls constructors for static and global C++ objects
  359.  
  360.     // Use this code to make your global RB methods known to RB:
  361.     for (int i = 0; i < sizeof(pluginMethodArray) / sizeof(REALmethodDefinition); ++i) {
  362.         REALRegisterMethod (&pluginMethodArray[i]);
  363.     }
  364.     
  365.     // Use this code to make any of your class definitions known to RB:
  366.     #if doExtentTheClass
  367.         REALRegisterClassExtension (&sampleClass);
  368.     #else
  369.         #ifdef WIN32
  370.             // #warning "Make sure you use RB 2.1a24 or later to create plugins for Windows!"
  371.         #endif
  372.         REALRegisterClass (&sampleClass);
  373.     #endif
  374. }
  375.